7300 // Shell.
7301 
7302 #include "types.h"
7303 #include "user.h"
7304 #include "fcntl.h"
7305 
7306 
7307 
7308 
7309 
7310 // Parsed command representation
7311 #define EXEC  1
7312 #define REDIR 2
7313 #define PIPE  3
7314 #define LIST  4
7315 #define BACK  5
7316 
7317 #define MAXARGS 10
7318 #define MAXDIRS 20
7319 #define MAXPATHSNAMES 20
7320 
7321 
7322 #define ENVVARIABLE ".env"
7323 #define C(x)  ((x)-'@')  // Control-x
7324 
7325 //data structure that will hold the optional paths the file in question can be in,
7326 //struct  paths {
7327 //  char *pathList[MAXDIRS];
7328 //}my_paths;
7329 
7330 // task 1 //
7331 static char paths[MAXDIRS][MAXPATHSNAMES];
7332 static int numOfDirs = 0;
7333 char EmptyLine[] = "\n";
7334 static char tempComm[128];
7335 
7336 void copyComm(char * orig, int path){
7337 	int i;
7338 	int j;
7339 	for (i=0; i<strlen(paths[path]) ; i++){
7340 		tempComm[i] = paths[path][i];
7341 	}
7342 	j=0;
7343 
7344 	tempComm[strlen(paths[path])] = '/';
7345 	for (i=strlen(paths[path])+1; j<strlen(orig); i++){
7346 		tempComm[i] = orig[j];
7347 		j = j + 1;
7348 	}
7349 
7350 }
7351 
7352 
7353 struct cmd {
7354   int type;
7355 };
7356 
7357 struct execcmd {
7358   int type;
7359   char *argv[MAXARGS];
7360   char *eargv[MAXARGS];
7361 };
7362 
7363 struct redircmd {
7364   int type;
7365   struct cmd *cmd;
7366   char *file;
7367   char *efile;
7368   int mode;
7369   int fd;
7370 };
7371 
7372 struct pipecmd {
7373   int type;
7374   struct cmd *left;
7375   struct cmd *right;
7376 };
7377 
7378 struct listcmd {
7379   int type;
7380   struct cmd *left;
7381   struct cmd *right;
7382 };
7383 
7384 struct backcmd {
7385   int type;
7386   struct cmd *cmd;
7387 };
7388 
7389 
7390 
7391 
7392 
7393 
7394 
7395 
7396 
7397 
7398 
7399 
7400 int fork1(void);  // Fork but panics on failure.
7401 void panic(char*);
7402 struct cmd *parsecmd(char*);
7403 
7404 
7405 // Execute cmd.  Never returns.
7406 void
7407 runcmd(struct cmd *cmd)
7408 {
7409   int p[2];
7410 //   int Workwell;
7411   int counter = 1;
7412 
7413 
7414   struct backcmd *bcmd;
7415   struct execcmd *ecmd;
7416   struct listcmd *lcmd;
7417   struct pipecmd *pcmd;
7418   struct redircmd *rcmd;
7419 
7420   if(cmd == 0)
7421     exit();
7422 
7423   switch(cmd->type){
7424   default:
7425     panic("runcmd");
7426 
7427   case EXEC:
7428     ecmd = (struct execcmd*)cmd;
7429     if(ecmd->argv[0] == 0)
7430       exit();
7431     exec(ecmd->argv[0], ecmd->argv);
7432 
7433 
7434 
7435     while (counter  < numOfDirs) {
7436   	copyComm(ecmd->argv[0], counter);
7437 	exec(tempComm, ecmd->argv);
7438 
7439 
7440 	printf(2, "exec %s failed. No such file: %s\n",
7441  ecmd->argv[0], tempComm);
7442     	counter = counter + 1;
7443     }
7444 
7445     printf(2, "exec %s failed\n", ecmd->argv[0]);
7446     break;
7447 
7448 
7449 
7450   case REDIR:
7451     rcmd = (struct redircmd*)cmd;
7452     close(rcmd->fd);
7453     if(open(rcmd->file, rcmd->mode) < 0){
7454       printf(2, "open %s failed\n", rcmd->file);
7455       exit();
7456     }
7457     runcmd(rcmd->cmd);
7458     break;
7459 
7460   case LIST:
7461     lcmd = (struct listcmd*)cmd;
7462     if(fork1() == 0)
7463       runcmd(lcmd->left);
7464     wait();
7465     runcmd(lcmd->right);
7466     break;
7467 
7468   case PIPE:
7469     pcmd = (struct pipecmd*)cmd;
7470     if(pipe(p) < 0)
7471       panic("pipe");
7472     if(fork1() == 0){
7473       close(1);
7474       dup(p[1]);
7475       close(p[0]);
7476       close(p[1]);
7477       runcmd(pcmd->left);
7478     }
7479     if(fork1() == 0){
7480       close(0);
7481       dup(p[0]);
7482       close(p[0]);
7483       close(p[1]);
7484       runcmd(pcmd->right);
7485     }
7486     close(p[0]);
7487     close(p[1]);
7488     wait();
7489     wait();
7490     break;
7491 
7492   case BACK:
7493     bcmd = (struct backcmd*)cmd;
7494     if(fork1() == 0)
7495       runcmd(bcmd->cmd);
7496     break;
7497   }
7498   exit();
7499 }
7500 int
7501 getcmd(char *buf, int nbuf)
7502 {
7503   printf(2, "$ ");
7504   memset(buf, 0, nbuf);
7505   gets(buf, nbuf);
7506   if(buf[0] == 0) // EOF
7507     return -1;
7508   return 0;
7509 }
7510 
7511 //our code
7512 
7513 void
7514 readAndParse(void)
7515 {
7516   int pEnvFile;
7517  // char  buf[MAXPATHSNAMES];
7518   int counter, bufCount;
7519   char c[1];
7520   counter = 0;
7521   bufCount = 0;
7522   int ourEOF;
7523   int i;
7524 
7525   pEnvFile = open(ENVVARIABLE, O_RDONLY);
7526 
7527   for (i=0 ; i<6 ; i ++){
7528 	  ourEOF = read(pEnvFile, c, 1);
7529   }
7530   	while(ourEOF > 0){
7531 
7532 		while ((ourEOF > 0) && (*c != ':')){
7533 
7534 			paths[numOfDirs][bufCount] = *c;
7535 			bufCount = bufCount + 1;
7536 			ourEOF = read(pEnvFile, c, 1);
7537 
7538 		}
7539 
7540 		paths[numOfDirs][bufCount] = 0;//end of path name
7541 		numOfDirs = numOfDirs + 1;
7542 		bufCount = 0;
7543 		if (ourEOF > 0){
7544 			read(pEnvFile, c, 1);}
7545 
7546 	}
7547   close(pEnvFile);
7548 }
7549 
7550 void
7551 printTest(void)
7552 {
7553 	printf(1,paths[0]); printf(1, EmptyLine);
7554 	printf(1,paths[1]); printf(1, EmptyLine);
7555 	printf(1,paths[2]); printf(1, EmptyLine);
7556 }
7557 
7558 
7559 
7560 
7561 int
7562 main(void)
7563 {
7564   static char buf[100];
7565   int fd;
7566 
7567 
7568 //   readAndParse();
7569 //  printTest(envPaths);
7570 
7571   // Assumes three file descriptors open.
7572   while((fd = open("console", O_RDWR)) >= 0){
7573     if(fd >= 3){
7574       close(fd);
7575       break;
7576     }
7577   }
7578 
7579   readAndParse();
7580   printTest();
7581 
7582 
7583 
7584   // Read and run input commands.
7585   while(getcmd(buf, sizeof(buf)) >= 0){
7586     if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
7587       // Clumsy but will have to do for now.
7588       // Chdir has no effect on the parent if run in the child.
7589       buf[strlen(buf)-1] = 0;  // chop \n
7590       if(chdir(buf+3) < 0)
7591         printf(2, "cannot cd %s\n", buf+3);
7592       continue;
7593     }
7594     if(fork1() == 0)
7595       runcmd(parsecmd(buf));
7596     wait();
7597   }
7598   exit();
7599 }
7600 void
7601 panic(char *s)
7602 {
7603   printf(2, "%s\n", s);
7604   exit();
7605 }
7606 
7607 int
7608 fork1(void)
7609 {
7610   int pid;
7611 
7612   pid = fork();
7613   if(pid == -1)
7614     panic("fork");
7615   return pid;
7616 }
7617 
7618 // Constructors
7619 
7620 struct cmd*
7621 execcmd(void)
7622 {
7623   struct execcmd *cmd;
7624 
7625   cmd = malloc(sizeof(*cmd));
7626   memset(cmd, 0, sizeof(*cmd));
7627   cmd->type = EXEC;
7628   return (struct cmd*)cmd;
7629 }
7630 
7631 struct cmd*
7632 redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)
7633 {
7634   struct redircmd *cmd;
7635 
7636   cmd = malloc(sizeof(*cmd));
7637   memset(cmd, 0, sizeof(*cmd));
7638   cmd->type = REDIR;
7639   cmd->cmd = subcmd;
7640   cmd->file = file;
7641   cmd->efile = efile;
7642   cmd->mode = mode;
7643   cmd->fd = fd;
7644   return (struct cmd*)cmd;
7645 }
7646 
7647 
7648 
7649 
7650 struct cmd*
7651 pipecmd(struct cmd *left, struct cmd *right)
7652 {
7653   struct pipecmd *cmd;
7654 
7655   cmd = malloc(sizeof(*cmd));
7656   memset(cmd, 0, sizeof(*cmd));
7657   cmd->type = PIPE;
7658   cmd->left = left;
7659   cmd->right = right;
7660   return (struct cmd*)cmd;
7661 }
7662 
7663 struct cmd*
7664 listcmd(struct cmd *left, struct cmd *right)
7665 {
7666   struct listcmd *cmd;
7667 
7668   cmd = malloc(sizeof(*cmd));
7669   memset(cmd, 0, sizeof(*cmd));
7670   cmd->type = LIST;
7671   cmd->left = left;
7672   cmd->right = right;
7673   return (struct cmd*)cmd;
7674 }
7675 
7676 struct cmd*
7677 backcmd(struct cmd *subcmd)
7678 {
7679   struct backcmd *cmd;
7680 
7681   cmd = malloc(sizeof(*cmd));
7682   memset(cmd, 0, sizeof(*cmd));
7683   cmd->type = BACK;
7684   cmd->cmd = subcmd;
7685   return (struct cmd*)cmd;
7686 }
7687 
7688 
7689 
7690 
7691 
7692 
7693 
7694 
7695 
7696 
7697 
7698 
7699 
7700 // Parsing
7701 
7702 char whitespace[] = " \t\r\n\v";
7703 char symbols[] = "<|>&;()";
7704 
7705 int
7706 gettoken(char **ps, char *es, char **q, char **eq)
7707 {
7708   char *s;
7709   int ret;
7710 
7711   s = *ps;
7712   while(s < es && strchr(whitespace, *s))
7713     s++;
7714   if(q)
7715     *q = s;
7716   ret = *s;
7717   switch(*s){
7718   case 0:
7719     break;
7720   case '|':
7721   case '(':
7722   case ')':
7723   case ';':
7724   case '&':
7725   case '<':
7726     s++;
7727     break;
7728   case '>':
7729     s++;
7730     if(*s == '>'){
7731       ret = '+';
7732       s++;
7733     }
7734     break;
7735   default:
7736     ret = 'a';
7737     while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
7738       s++;
7739     break;
7740   }
7741   if(eq)
7742     *eq = s;
7743 
7744   while(s < es && strchr(whitespace, *s))
7745     s++;
7746   *ps = s;
7747   return ret;
7748 }
7749 
7750 int
7751 peek(char **ps, char *es, char *toks)
7752 {
7753   char *s;
7754 
7755   s = *ps;
7756   while(s < es && strchr(whitespace, *s))
7757     s++;
7758   *ps = s;
7759   return *s && strchr(toks, *s);
7760 }
7761 
7762 struct cmd *parseline(char**, char*);
7763 struct cmd *parsepipe(char**, char*);
7764 struct cmd *parseexec(char**, char*);
7765 struct cmd *nulterminate(struct cmd*);
7766 
7767 struct cmd*
7768 parsecmd(char *s)
7769 {
7770   char *es;
7771   struct cmd *cmd;
7772 
7773   es = s + strlen(s);
7774   cmd = parseline(&s, es);
7775   peek(&s, es, "");
7776   if(s != es){
7777     printf(2, "leftovers: %s\n", s);
7778     panic("syntax");
7779   }
7780   nulterminate(cmd);
7781   return cmd;
7782 }
7783 
7784 struct cmd*
7785 parseline(char **ps, char *es)
7786 {
7787   struct cmd *cmd;
7788 
7789   cmd = parsepipe(ps, es);
7790   while(peek(ps, es, "&")){
7791     gettoken(ps, es, 0, 0);
7792     cmd = backcmd(cmd);
7793   }
7794   if(peek(ps, es, ";")){
7795     gettoken(ps, es, 0, 0);
7796     cmd = listcmd(cmd, parseline(ps, es));
7797   }
7798   return cmd;
7799 }
7800 struct cmd*
7801 parsepipe(char **ps, char *es)
7802 {
7803   struct cmd *cmd;
7804 
7805   cmd = parseexec(ps, es);
7806   if(peek(ps, es, "|")){
7807     gettoken(ps, es, 0, 0);
7808     cmd = pipecmd(cmd, parsepipe(ps, es));
7809   }
7810   return cmd;
7811 }
7812 
7813 struct cmd*
7814 parseredirs(struct cmd *cmd, char **ps, char *es)
7815 {
7816   int tok;
7817   char *q, *eq;
7818 
7819   while(peek(ps, es, "<>")){
7820     tok = gettoken(ps, es, 0, 0);
7821     if(gettoken(ps, es, &q, &eq) != 'a')
7822       panic("missing file for redirection");
7823     switch(tok){
7824     case '<':
7825       cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
7826       break;
7827     case '>':
7828       cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
7829       break;
7830     case '+':  // >>
7831       cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
7832       break;
7833     }
7834   }
7835   return cmd;
7836 }
7837 
7838 
7839 
7840 
7841 
7842 
7843 
7844 
7845 
7846 
7847 
7848 
7849 
7850 struct cmd*
7851 parseblock(char **ps, char *es)
7852 {
7853   struct cmd *cmd;
7854 
7855   if(!peek(ps, es, "("))
7856     panic("parseblock");
7857   gettoken(ps, es, 0, 0);
7858   cmd = parseline(ps, es);
7859   if(!peek(ps, es, ")"))
7860     panic("syntax - missing )");
7861   gettoken(ps, es, 0, 0);
7862   cmd = parseredirs(cmd, ps, es);
7863   return cmd;
7864 }
7865 
7866 struct cmd*
7867 parseexec(char **ps, char *es)
7868 {
7869   char *q, *eq;
7870   int tok, argc;
7871   struct execcmd *cmd;
7872   struct cmd *ret;
7873 
7874   if(peek(ps, es, "("))
7875     return parseblock(ps, es);
7876 
7877   ret = execcmd();
7878   cmd = (struct execcmd*)ret;
7879 
7880   argc = 0;
7881   ret = parseredirs(ret, ps, es);
7882   while(!peek(ps, es, "|)&;")){
7883     if((tok=gettoken(ps, es, &q, &eq)) == 0)
7884       break;
7885     if(tok != 'a')
7886       panic("syntax");
7887     cmd->argv[argc] = q;
7888     cmd->eargv[argc] = eq;
7889     argc++;
7890     if(argc >= MAXARGS)
7891       panic("too many args");
7892     ret = parseredirs(ret, ps, es);
7893   }
7894   cmd->argv[argc] = 0;
7895   cmd->eargv[argc] = 0;
7896   return ret;
7897 }
7898 
7899 
7900 // NUL-terminate all the counted strings.
7901 struct cmd*
7902 nulterminate(struct cmd *cmd)
7903 {
7904   int i;
7905   struct backcmd *bcmd;
7906   struct execcmd *ecmd;
7907   struct listcmd *lcmd;
7908   struct pipecmd *pcmd;
7909   struct redircmd *rcmd;
7910 
7911   if(cmd == 0)
7912     return 0;
7913 
7914   switch(cmd->type){
7915   case EXEC:
7916     ecmd = (struct execcmd*)cmd;
7917     for(i=0; ecmd->argv[i]; i++)
7918       *ecmd->eargv[i] = 0;
7919     break;
7920 
7921   case REDIR:
7922     rcmd = (struct redircmd*)cmd;
7923     nulterminate(rcmd->cmd);
7924     *rcmd->efile = 0;
7925     break;
7926 
7927   case PIPE:
7928     pcmd = (struct pipecmd*)cmd;
7929     nulterminate(pcmd->left);
7930     nulterminate(pcmd->right);
7931     break;
7932 
7933   case LIST:
7934     lcmd = (struct listcmd*)cmd;
7935     nulterminate(lcmd->left);
7936     nulterminate(lcmd->right);
7937     break;
7938 
7939   case BACK:
7940     bcmd = (struct backcmd*)cmd;
7941     nulterminate(bcmd->cmd);
7942     break;
7943   }
7944   return cmd;
7945 }
7946 
7947 
7948 
7949 
